#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "rngs.h"
#include <math.h>
#include "testHelper.c"

#define NOISY_TEST 1

int checkAdventurer(int testCardPos, struct gameState *testState) {
  int functionError, drawnTreasure, cardDrawn, z;
  int temphand[MAX_HAND];
  struct gameState controlState;

  z = 0;
  drawnTreasure = 0;
  
  memcpy (&controlState, testState, sizeof(struct gameState));
  functionError = adventurerCard(testState, whoseTurn(testState));
  if(functionError != 0){
    printf("adventurerCard failed. errno: %d\n", functionError);
    return 0;
  }
  printf("Current Player deckCount = %d\n", testState->deckCount[whoseTurn(testState)]);
  /* SIMULATE THE CARD EFFECT */
  while(drawnTreasure < 2){
    if(controlState.deckCount[whoseTurn(&controlState)] < 1){
      shuffle(whoseTurn(&controlState), &controlState);
    }
    drawCard(whoseTurn(&controlState), &controlState);
    cardDrawn = controlState.hand[whoseTurn(&controlState)][controlState.handCount[whoseTurn(&controlState)] - 1];
    if(cardDrawn == copper || cardDrawn == silver || cardDrawn == gold){
      drawnTreasure++;
    }
    else{
      temphand[z]=cardDrawn;
      controlState.handCount[whoseTurn(&controlState)]--;
      z++;
    }
  }
  if(z % 10 == 0){
    z = 0;
  }
  
  while(z-1 >= 0){
    controlState.discard[whoseTurn(&controlState)][controlState.discardCount[whoseTurn(&controlState)]++] = temphand[z-1];
    z = z-1;
  }


  if(functionError != 0){
    printf("adventurerCard failed. errno: %d\n", functionError);
    return 0;
  }
					    
  assert(functionError == 0); //no error playing the card
  
  //test to see if both the states are the same
  if(memcmp(&controlState, testState, sizeof(struct gameState)) == 0){
    return 0;
  }
  else{
    gameStateDiff(&controlState, testState);
    return 1;
  }
}

int main () {
  int i, j, n, numPlayers, currentPlayer, seed, testCardPos, success, failure;

  int k[10] = {adventurer, council_room, feast, gardens, mine,
	       outpost, smithy, village, baron, great_hall};

  struct gameState G;
  
  printf ("***TESTING ADVENTURER***\n");

  success = 0;
  failure = 0;
  PutSeed(floor(Random() * MODULUS));

  for (n = 0; n < 2000; n++) {
    /* Fill the Game State with garbage */
    for (i = 0; i < sizeof(struct gameState); i++) {
      ((char*)&G)[i] = floor(Random() * 256);
    }
    //initialize new game
    numPlayers = floor(Random() * PLAYER_RANGE) + 2;
    seed = floor(Random() * 1000) + 1;
    initializeGame(numPlayers, k, seed, &G);
    
    for (i = 0; i < numPlayers; i++){
      G.deckCount[i] = floor(Random() * MAX_DECK);
      G.discardCount[i] = floor(Random() * MAX_DECK);
      G.handCount[i] = floor(Random() * MAX_HAND);
      /*set each of the cards in a player's hand to something.
	this results in appx. 10% of cards being treasure cards. */
      for (j = 0; j < G.deckCount[i]; j++){
	G.hand[i][j] = floor(Random() * treasure_map); 
      }
    }
    currentPlayer = floor(Random() * numPlayers); //define a current random player
    G.whoseTurn = currentPlayer; //set the game's current player to selected player
    testCardPos = floor(Random() * G.handCount[currentPlayer]); //define a random card in the current player's hand to test
    G.hand[currentPlayer][testCardPos] = adventurer; //set that card to a adventurer

    /* player's handCount = 0 10% of the time to force shuffle */
    if(n % 10 == 0){
      G.deckCount[currentPlayer] = 0;
    }

    if(checkAdventurer(testCardPos, &G) == 0){
      success++;
    }
    else{
      failure++;
    }
  }

  printf ("\n***TESTS COMPLETE***\n***SUMMARY\n***Successful Tests: %d\n***Failed Tests: %d\n\n", success, failure); 

  return 0;
}
